﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using System.Text;

public class WordRegion : MonoBehaviour {
    public TextPreview textPreview;
    public Compliment compliment;
    public Transform lineWordsTr;
    public RectTransform parentTr, rootCanvas;

    private List<LineWord> lines = new List<LineWord>();
    private List<string> validWords = new List<string>();

    private GameLevel gameLevel;
    private readonly float cellSize = 80f;

    public static WordRegion instance;

    private void Awake()
    {
        instance = this;
    }

    public void Load(GameLevel gameLevel)
    {
        this.gameLevel = gameLevel;

        var wordList = CUtils.BuildListFromString<string>(this.gameLevel.answers);
        validWords = CUtils.BuildListFromString<string>(this.gameLevel.validWords);

        CrosswordGenerator generator = new CrosswordGenerator();
        generator.SetWords(wordList);
        var crossedWords = generator.Generate();
        wordList = crossedWords.Select(x => x.word).ToList();

        string[] levelProgress = GetLevelProgress();
        bool useProgress = false;

        if (levelProgress.Length != 0)
        {
            useProgress = CheckLevelProgress(levelProgress, wordList);
            if (!useProgress) ClearLevelProgress();
        }

        int lineIndex = 0;
        foreach (var word in wordList)
        {
            LineWord line = Instantiate(MonoUtils.instance.lineWord);
            line.name = "LineWord (" + word + ")";
            line.answer = word.ToUpper();
            line.cellSize = cellSize;
            line.crossedWord = crossedWords[lineIndex];
            line.Build();

            if (useProgress)
            {
                line.SetProgress(levelProgress[lineIndex]);
            }

            line.transform.SetParent(lineWordsTr);
            line.transform.localScale = Vector3.one;
            line.transform.localPosition = Vector3.zero;

            lines.Add(line);
            lineIndex++;
        }

        SetLinesPosition();
    }

    private void SetLinesPosition()
    {
        var distance = cellSize * (1 + Const.CELL_GAP_COEF);
        foreach(var line in lines)
        {
            Position pos = line.crossedWord.position;
            line.transform.localPosition = new Vector2(pos.x, pos.y) * distance;
        }

        float minX = int.MaxValue, minY = int.MaxValue, maxX = int.MinValue, maxY = int.MinValue;

        foreach(var line in lines)
        {
            foreach(var cell in line.cells)
            {
                minX = Mathf.Min(minX, cell.transform.position.x);
                minY = Mathf.Min(minY, cell.transform.position.y);
                maxX = Mathf.Max(maxX, cell.transform.position.x);
                maxY = Mathf.Max(maxY, cell.transform.position.y);
            }
        }

        minX -= cellSize / 200f;
        minY -= cellSize / 200f;
        maxX += cellSize / 200f;
        maxY += cellSize / 200f;

        Vector3 center = new Vector3((maxX + minX) / 2f, (maxY + minY) / 2f);
        foreach(Transform child in lineWordsTr)
        {
            child.position += lineWordsTr.position - center;
        }

        float width = (maxX - minX) * 100f;
        float height = (maxY - minY) * 100f;
        float ratio = width / height;

        float maxWidth = rootCanvas.rect.width - 64f;
        float maxHeight = 600f;

        if (ratio < maxWidth / maxHeight)
        {
            lineWordsTr.localScale = Vector3.one * (Mathf.Min(maxHeight / height, 1));
        }
        else
        {
            lineWordsTr.localScale = Vector3.one * (Mathf.Min(maxWidth / width, 1));
        }

        float boardWidth = width * lineWordsTr.localScale.x + 64f;
        float boardHeight = height * lineWordsTr.localScale.y + 80f;
        boardWidth = Mathf.Max(600f, boardWidth);
        boardHeight = Mathf.Max(450f, boardHeight);

        parentTr.sizeDelta = new Vector2(boardWidth, boardHeight);
    }

    public void CheckAnswer(string checkWord)
    {
        LineWord line = lines.Find(x => x.answer == checkWord);
        if (line != null)
        {
            if (!line.isShown)
            {
                textPreview.SetAnswerColor();
                line.ShowAnswer();
                CheckGameComplete();

                Sound.instance.Play(Sound.Others.Match);
            }
            else
            {
                textPreview.SetExistColor();
            }
        }
        else if (validWords.Contains(checkWord.ToLower()))
        {
            ExtraWord.instance.ProcessWorld(checkWord);
        }
        else
        {
            textPreview.SetWrongColor();
        }

        textPreview.FadeOut();
    }

    private void CheckGameComplete()
    {
        SaveLevelProgress();
        var isNotShown = lines.Find(x => !x.isShown);
        if (isNotShown == null)
        {
            ClearLevelProgress();
            MainController.instance.OnComplete();

            if (lines.Count >= 6)
            {
                compliment.ShowRandom();
            }
        }
    }

    public void HintClick()
    {
        int ballance = CurrencyController.GetBalance();
        int cost = ConfigController.Config.hintCost;

        if (ballance >= cost)
        {
            var line = lines.Find(x => !x.isShown);

            if (line != null)
            {
                line.ShowHint();
                CurrencyController.DebitBalance(cost);
                CheckGameComplete();

                Prefs.AddToNumHint(Prefs.CurrentLevel);
            }
        }
        else
        {
            DialogController.instance.ShowDialog(DialogType.Shop);
        }
        Sound.instance.PlayButton();
    }

    public void PickBoxClick()
    {
        if (GameState.enablePickBox)
        {
            Toast.instance.ShowMessage("Tap on a box to open it");
            return;
        }

        int ballance = CurrencyController.GetBalance();
        int cost = ConfigController.Config.pickBoxCost;

        if (ballance >= cost)
        {
            Toast.instance.ShowMessage("Tap on a box to open it");
            CurrencyController.DebitBalance(cost);
            GameState.enablePickBox = true;
        }
        else
        {
            DialogController.instance.ShowDialog(DialogType.Shop);
        }
    }

    public void SaveLevelProgress()
    {
        if (!Prefs.IsLastLevel()) return;

        List<string> results = new List<string>();
        foreach(var line in lines)
        {
            StringBuilder sb = new StringBuilder();
            foreach(var cell in line.cells)
            {
                sb.Append(cell.IsShown ? "1" : "0");
            }
            results.Add(sb.ToString());
        }

        Prefs.LevelProgress = results.ToArray();
    }

    public string[] GetLevelProgress()
    {
        if (!Prefs.IsLastLevel()) return new string[0];
        return Prefs.LevelProgress;
    }

    public void ClearLevelProgress()
    {
        if (!Prefs.IsLastLevel()) return;
        CPlayerPrefs.DeleteKey("level_progress");
    }

    public bool CheckLevelProgress(string[] levelProgress, List<string> wordList)
    {
        if (levelProgress.Length != wordList.Count) return false;

        for (int i = 0; i < wordList.Count; i++)
        {
            if (levelProgress[i].Length != wordList[i].Length) return false;
        }
        return true;
    }

    private void OnApplicationPause(bool pause)
    {
        if (!pause)
        {
            Timer.Schedule(this, 0.5f, () =>
            {
                UpdateBoard();
            });
        }
    }

    private void UpdateBoard()
    {
        string[] progress = GetLevelProgress();
        if (progress.Length == 0) return;

        int i = 0;
        foreach(var line in lines)
        {
            //line.SetProgress(progress[i]);
            i++;
        }
    }
}
